using UnityEngine;
using System.Collections;
using System.IO;
using System;
using HT.Framework;

namespace TG
{
    public class BalanceInputManager : HTBehaviour
    {
        //启用自动化
        protected override bool IsAutomate => true;

        static protected BalanceInputManager _instance;

        static public BalanceInputManager Instance
        {
            get { return _instance; }
        }

        //传感器横坐标
        private const float L = 178.19f;

        //纵坐标
        public float M = 198.19f;

        //用户体重 kg
        private float userWeight;

        // 摔倒临界值
        private float fallThreshold = 0;

        // 开始检测摔倒
        private bool chackFall = false;

        //用户身高 mm
        private float userHeight;

        private float xSoftLimit = 500000 * 8 / 2; //主动模式软件限位
        private float ySoftLimit = 50000 * 8 / 2;
        private float xGravity; //重心位置
        private float yGravity;
        private float left_MaxValue = 8;
        private float right_MaxValue = 8;
        private float forward_MaxValue = 8;
        private float back_MaxValue = 4.5f;

        private float righleft_Proportion = 0.05f;
        private float forward_Proportion = 0.05f;

        public float hAxis
        {
            get
            {
                if (MainGame.Instance.isRunning) return _hAxis;
                else return 0;
            }
        }

        public float vAxis
        {
            get
            {
                if (MainGame.Instance.isRunning) return _vAxis;
                else return 0;
            }
        }

        private float _hAxis;
        private float _vAxis;
        public float x;
        public float y;
        public float pointPosX = 0;
        public float pointPosY = 0;

        private float coefficient = 1;

        private BaseGameConfig gameConfig;

        // 0 为上下同方向 1 为上下反方向
        // 1 是否忽略校准值为负的情况            1
        // 2 主动模式，纵向系数（乘）            1.3
        // 3 坐姿，横向系数（加）               1
        // 4 坐姿，纵向系数（加）               1
        // 5 站姿，横向系数（加）               0
        // 6 站姿，纵向系数（加）               0
        public int inputUp;
        // 主动模式，纵向系数（乘）
        private float zhuDongParamY = 1;

        // 是否忽略校准值为负的情况
        private bool ignoreNegative = false;

        // 坐姿，横向系数（加）
        private float seatParamX = 0;

        // 坐姿，纵向系数（加）
        private float seatParamY = 0;

        // 站姿，横向系数（加）
        private float standParamX = 0;

        // 站姿，纵向系数（加）
        private float standParamY = 0;

        // 校准值
        public double standA;
        public double standB;
        public double standC;
        public double standD;

        public double seatA;
        public double seatB;
        public double seatC;
        public double seatD;

        private string[] caliStr = new string[] { "A", "B", "C", "D" };

        private string standPath;
        private string seatPath;
        private bool writeCalibration = false;

        protected override void Awake()
        {
            if (_instance != null)
            {
                Destroy(gameObject);
                return;
            }
            _instance = this;
            DontDestroyOnLoad(gameObject);
            string[] configs = System.IO.File.ReadAllLines(Application.streamingAssetsPath + $"/config.txt");
            inputUp = int.Parse(configs[1]);
            ignoreNegative = int.Parse(configs[3]) == 1;
            zhuDongParamY = float.Parse(configs[5]);
            seatParamX = float.Parse(configs[7]);
            seatParamY = float.Parse(configs[9]);
            standParamX = float.Parse(configs[11]);
            standParamY = float.Parse(configs[13]);
        }

        private string GetConfig(string line)
        {
            int index = line.IndexOf("//");
            if (index >= 0)
                return line.Substring(0, index).Trim();
            else
                return line.Trim();
        }

        /// <summary>
        /// 设置控制回正阈值
        /// </summary>
        public void SetProportion(float num)
        {
            righleft_Proportion = num;
            forward_Proportion = num;
        }


        public void Initialize(ref BaseGameConfig gameConfig)
        {
            this.gameConfig = gameConfig;
            xGravity = gameConfig.gravityX;
            yGravity = gameConfig.gravityY;
            userWeight = gameConfig.playWeight;
            userHeight = gameConfig.playHeight;

            xGravity = Mathf.Clamp(xGravity, -left_MaxValue + 0.1f, right_MaxValue - 0.1f);
            yGravity = Mathf.Clamp(yGravity, -back_MaxValue + 0.1f, forward_MaxValue - 0.1f);

            Debug.Log($"ignoreNegative = {ignoreNegative}, zhuDongParamY = {zhuDongParamY}, " +
                      $"standParamX = {standParamX}, standParamY = {standParamY}, seatParamX = {seatParamX}, seatParamY = {seatParamY},xGravity = {xGravity}, yGravity = {yGravity}");

            fallThreshold = userWeight * 0.3f;

            if (gameConfig.posture == Posture.Stand)
            {
                xSoftLimit = Mathf.Max(1, gameConfig.initiative.xMaxAngle / 360f * 480 * 100000);
                ySoftLimit = Mathf.Max(1, gameConfig.initiative.yMaxAngle / 360f * 100 * 100000);
            }
            else if (gameConfig.posture == Posture.Sit)
            {
                xSoftLimit = Mathf.Max(1, gameConfig.initiative.xMaxAngle / 360f * 240 * 100000);
                ySoftLimit = Mathf.Max(1, gameConfig.initiative.yMaxAngle / 360f * 100 * 100000);
            }

            chackFall = true;

            string name = gameConfig.posture == Posture.Stand ? "站姿" : "坐姿";
            string fileName = gameConfig.posture == Posture.Stand ? "calibrationStand.txt" : "calibrationSeat.txt";

            DirectoryInfo dirInfo = new DirectoryInfo(Application.dataPath);
            string path = Path.Combine(dirInfo.Parent.FullName, fileName);
            bool exist = File.Exists(path);
            Debug.Log($"{name}校准值文件 {path} 是否存在 {exist}");

            if (gameConfig.posture == Posture.Stand)
            {
                standPath = path;
                Debug.Log($"standPath = {standPath}");
            }
            else
            {
                seatPath = path;
                Debug.Log($"seatPath = {seatPath}");
            }

            if (exist)
            {
                var lines = File.ReadAllLines(path);
                if (gameConfig.posture == Posture.Stand)
                {
                    foreach (var line in lines)
                    {
                        if (line.StartsWith("standA="))
                        {
                            string[] splits = line.Split('=');
                            standA = double.Parse(splits[1].Trim());
                        }
                        else if (line.StartsWith("standB="))
                        {
                            string[] splits = line.Split('=');
                            standB = double.Parse(splits[1].Trim());
                        }
                        else if (line.StartsWith("standC="))
                        {
                            string[] splits = line.Split('=');
                            standC = double.Parse(splits[1].Trim());
                        }
                        else if (line.StartsWith("standD="))
                        {
                            string[] splits = line.Split('=');
                            standD = double.Parse(splits[1].Trim());
                        }
                    }

                    Debug.Log($"读取校准值 standA {standA} standB {standB} standC {standC} standD {standD}");
                }
                else
                {
                    foreach (var line in lines)
                    {
                        if (line.StartsWith("seatA="))
                        {
                            string[] splits = line.Split('=');
                            seatA = double.Parse(splits[1].Trim());
                        }
                        else if (line.StartsWith("seatB="))
                        {
                            string[] splits = line.Split('=');
                            seatB = double.Parse(splits[1].Trim());
                        }
                        else if (line.StartsWith("seatC="))
                        {
                            string[] splits = line.Split('=');
                            seatB = double.Parse(splits[1].Trim());
                        }
                        else if (line.StartsWith("seatD="))
                        {
                            string[] splits = line.Split('=');
                            seatD = double.Parse(splits[1].Trim());
                        }
                    }
                    Debug.Log($"读取校准值 seatA {seatA} seatB {seatB} seatC {seatC} seatD {seatD}");
                }
            }
            else
            {
                Debug.Log($"创建{name}校准值文件 {path}");
                var fs = File.Create(path);
                fs.Close();
                writeCalibration = true;
            }
        }

        void Update()
        {
            if (gameConfig != null && gameConfig.isTest)
            {
                _hAxis = Input.GetAxis("Horizontal");
                _vAxis = Input.GetAxis("Vertical");
            }

            if (Input.GetKeyDown(KeyCode.F2))
                writeCalibration = true;
        }

        float tmpx;
        float tmpy;

        public void SetValue(ref double[] value)
        {
            //Debug.LogError("获得SetValue vAxis 和 hAxis 值");
            if (value == null || value.Length < 4) return;

            if (writeCalibration)
            {
                WriteCalibration(value);
                writeCalibration = false;
            }

            try
            {
                chackFall = true;

                if (gameConfig.posture == Posture.Stand)
                {
                    if (ignoreNegative)
                    {
                        value[0] -= Math.Max(standA, 0);
                        value[1] -= Math.Max(standB, 0);
                        value[2] -= Math.Max(standC, 0);
                        value[3] -= Math.Max(standD, 0);
                    }
                    else
                    {
                        value[0] -= standA;
                        value[1] -= standB;
                        value[2] -= standC;
                        value[3] -= standD;
                    }
                }
                else if (gameConfig.posture == Posture.Sit)
                {
                    if (ignoreNegative)
                    {
                        value[0] -= Math.Max(seatA, 0);
                        value[1] -= Math.Max(seatB, 0);
                        value[2] -= Math.Max(seatC, 0);
                        value[3] -= Math.Max(seatD, 0);
                    }
                    else
                    {
                        value[0] -= seatA;
                        value[1] -= seatB;
                        value[2] -= seatC;
                        value[3] -= seatD;
                    }
                }

                for (int i = 0; i < 4; i++)
                    Debug.Log("EtherCAT 减去校准值后的值 " + i + "  value = " + value[i]);

                double total = value[0] + value[1] + value[2] + value[3];
                Debug.Log($"重量为 {total}");

                if (total <= 10)
                {
                    _hAxis = 0;
                    _vAxis = 0;
                    return;
                }

                if (gameConfig.posture == Posture.Stand)
                {
                    Debug.Log("SetValue Posture.Stand ===== ");

                    tmpx = (float)((value[2] + value[3]) - (value[0] + value[1])) * L / userWeight;
                    tmpy = (float)((value[0] + value[2]) - (value[1] + value[3])) * M / userWeight;
                }
                else if (gameConfig.posture == Posture.Sit)
                {
                    Debug.Log("SetValue Posture.Sit ===== ");

                    tmpx = (float)((value[0] + value[2]) - (value[1] + value[3])) * L / userWeight *
                           1.2f; //临时*1.2增加操作灵敏
                    tmpy = (float)((value[1] + value[0]) - (value[3] + value[2])) * M / userWeight;
                }

                Debug.Log($"L = {L}, M = {M}, userHeight = {userHeight}, userWeight = {userWeight}");
                Debug.Log($"tmpx = {tmpx}, tmpy = {tmpy}");

                float h = 0.5527f * userHeight;
                float xvalue = tmpx / h;
                float yvalue = tmpy / h;
                x = Mathf.Asin(xvalue);
                y = Mathf.Asin(yvalue);

                Debug.Log($"xvalue = {xvalue}, yvalue = {yvalue}");
                Debug.Log($"x1 = {x}, y1 = {y}");

                // 重心偏移(坐姿与站姿X轴的重心起始位置偏移方向相反)
                if (gameConfig.posture == Posture.Stand)
                {
                    x = 180 * x / Mathf.PI + standParamX;
                    y = 180 * y / Mathf.PI + standParamY;
                }
                else if (gameConfig.posture == Posture.Sit)
                {
                    x = (180 * x / Mathf.PI) + seatParamX;
                    y = (180 * y / Mathf.PI) + seatParamY;
                }

                Debug.Log($"x2 = {x}, y2 = {y}");

                x -= xGravity;
                y -= yGravity;

                x = Mathf.Clamp(x, -left_MaxValue, right_MaxValue);
                y = Mathf.Clamp(y, -back_MaxValue, forward_MaxValue);

                x = (x > 0) ? (x / right_MaxValue) : (x / left_MaxValue);
                y = (y > 0) ? (y / forward_MaxValue) : (y / back_MaxValue);

                Debug.Log($"x3 = {x}, y3 = {y}");

                _hAxis = (Mathf.Abs(x) <= GameSetting.ignoreX) ? 0 : x;
                _vAxis = (Mathf.Abs(y) <= GameSetting.ignoreY) ? 0 : y;

                Debug.Log($"hAxis = {_hAxis}, vAxis = {_vAxis} ");
            }
            catch (System.Exception e)
            {
                Debug.LogWarning(e);
            }
        }

        public void SetAxisValue(ref int[] value)
        {
            if (value == null || value.Length < 2) return;
            try
            {
                if (gameConfig.posture == Posture.Stand)
                {
                    pointPosX = x = Mathf.Clamp(-value[0] / xSoftLimit, -1, 1);
                    pointPosY = y = Mathf.Clamp(value[1] / ySoftLimit, -1, 1);
                }
                else if (gameConfig.posture == Posture.Sit)
                {
                    pointPosX = x = Mathf.Clamp(value[0] / xSoftLimit, -1, 1);
                    pointPosY = y = Mathf.Clamp(value[1] / ySoftLimit, -1, 1);
                }

                pointPosX *= zhuDongParamY;
                pointPosY *= zhuDongParamY;

                _hAxis = (Mathf.Abs(pointPosX) <= righleft_Proportion) ? 0 : pointPosX;
                _vAxis = (Mathf.Abs(pointPosY) <= forward_Proportion) ? 0 : pointPosY;
                Debug.LogError(string.Format("hAxis = {0} vAxis = {1}", hAxis, vAxis));
            }
            catch (System.Exception e)
            {
                Debug.LogWarning(e);
            }
        }


        /// <summary>
        /// 主动模式 多模式，  根据不同的主动模式，执行不同方向的静态和主动
        /// </summary>
        /// <param name="value">静态传值</param>
        /// <param name="axisValue">主动传值</param>
        public void SetAxisValueAndValue(ref double[] value, ref int[] axisValue)
        {
            Debug.Log("SetAxisValueAndValue " + gameConfig.rolloverModel);
            if (value == null || value.Length < 4) return;
            if (axisValue == null || axisValue.Length < 2) return;

            if (writeCalibration)
            {
                WriteCalibration(value);
                writeCalibration = false;
            }

            if (gameConfig.posture == Posture.Stand)
            {
                if (ignoreNegative)
                {
                    value[0] -= Math.Max(standA, 0);
                    value[1] -= Math.Max(standB, 0);
                    value[2] -= Math.Max(standC, 0);
                    value[3] -= Math.Max(standD, 0);
                }
                else
                {
                    value[0] -= standA;
                    value[1] -= standB;
                    value[2] -= standC;
                    value[3] -= standD;
                }
            }
            else if (gameConfig.posture == Posture.Sit)
            {
                if (ignoreNegative)
                {
                    value[0] -= Math.Max(seatA, 0);
                    value[1] -= Math.Max(seatB, 0);
                    value[2] -= Math.Max(seatC, 0);
                    value[3] -= Math.Max(seatD, 0);
                }
                else
                {
                    value[0] -= seatA;
                    value[1] -= seatB;
                    value[2] -= seatC;
                    value[3] -= seatD;
                }
            }

            double total = value[0] + value[1] + value[2] + value[3];
            Debug.Log($"重量为 {total}");

            if (total <= 10)
            {
                _hAxis = 0;
                _vAxis = 0;
                return;
            }

            if (gameConfig.rolloverModel == 0)
            {
                //前后翻转
                try
                {
                    //静态
                    chackFall = true;
                    if (gameConfig.posture == Posture.Stand)
                    {
                        Debug.Log("前后翻转 Posture.Stand ===== ");
                        tmpx = (float)((value[2] + value[3]) - (value[0] + value[1])) * L / userWeight;
                    }
                    else if (gameConfig.posture == Posture.Sit)
                    {
                        Debug.Log("前后翻转 Posture.Sit ===== ");
                        tmpx = (float)((value[0] + value[2]) - (value[1] + value[3])) * L / userWeight *
                               1.2f; //临时*1.2增加操作灵敏
                    }

                    float h = 0.5527f * userHeight;
                    float xvalue = tmpx / h;

                    //if (xvalue < -1)
                    //    xvalue = -1;
                    //else if (xvalue > 1)
                    //    xvalue = 1;

                    Debug.Log($"L = {L}, userWeight = {userWeight}");
                    Debug.Log($"tmpx = {tmpx}");

                    x = Mathf.Asin(xvalue);

                    Debug.Log($"xvalue = {xvalue}");
                    Debug.Log($"x1 = {x}");

                    // 重心偏移(坐姿与站姿X轴的重心起始位置偏移方向相反)
                    if (gameConfig.posture == Posture.Stand)
                        x = 180 * x / Mathf.PI + standParamX;
                    else if (gameConfig.posture == Posture.Sit)
                        x = (180 * x / Mathf.PI) + seatParamX;

                    Debug.Log($"x2 = {x}");

                    x -= xGravity;
                    x = Mathf.Clamp(x, -left_MaxValue, right_MaxValue);
                    x = (x > 0) ? (x / right_MaxValue) : (x / left_MaxValue);

                    //主动
                    if (gameConfig.posture == Posture.Stand)
                        y = Mathf.Clamp(axisValue[1] / ySoftLimit, -1, 1);
                    else if (gameConfig.posture == Posture.Sit)
                        y = Mathf.Clamp(axisValue[1] / ySoftLimit, -1, 1);

                    Debug.Log($"x3 = {x}, y3 = {y}");

                    y *= zhuDongParamY;

                    _hAxis = (Mathf.Abs(x) <= GameSetting.ignoreX) ? 0 : x;
                    _vAxis = (Mathf.Abs(y) <= GameSetting.ignoreY) ? 0 : y;

                    Debug.Log($"前后翻转 hAxis = {_hAxis}, vAxis = {_vAxis}");
                }
                catch (System.Exception e)
                {
                    Debug.LogWarning(e);
                }
            }
            else if (gameConfig.rolloverModel == 1)
            {
                //左右翻转

                try
                {
                    //静态
                    chackFall = true;
                    if (gameConfig.posture == Posture.Stand)
                    {
                        Debug.Log("左右翻转 Posture.Stand ===== ");
                        tmpy = (float)((value[0] + value[2]) - (value[1] + value[3])) * M / userWeight;
                    }
                    else if (gameConfig.posture == Posture.Sit)
                    {
                        Debug.Log("左右翻转 Posture.Sit ===== ");
                        tmpy = (float)((value[1] + value[0]) - (value[3] + value[2])) * M / userWeight;
                    }

                    float h = 0.5527f * userHeight;
                    float yvalue = tmpy / h;

                    //if (yvalue < -1)
                    //    yvalue = -1;
                    //else if (yvalue > 1)
                    //    yvalue = 1;

                    Debug.Log($"L = {L}, userWeight = {userWeight}");
                    Debug.Log($"tmpy = {tmpy}");

                    y = Mathf.Asin(yvalue);

                    Debug.Log($"yvalue = {yvalue}");
                    Debug.Log($"y1 = {y}");

                    if (gameConfig.posture == Posture.Stand)
                        y = 180 * y / Mathf.PI + standParamY;
                    else if (gameConfig.posture == Posture.Sit)
                        y = (180 * y / Mathf.PI) + seatParamY;

                    Debug.Log($"y2 = {y}");

                    y -= yGravity;
                    y = Mathf.Clamp(y, -back_MaxValue, forward_MaxValue);
                    y = (y > 0) ? (y / forward_MaxValue) : (y / back_MaxValue);

                    //主动
                    if (gameConfig.posture == Posture.Stand)
                        x = Mathf.Clamp(-axisValue[0] / xSoftLimit, -1, 1);
                    else if (gameConfig.posture == Posture.Sit)
                        x = Mathf.Clamp(axisValue[0] / xSoftLimit, -1, 1);

                    Debug.Log($"x3 = {x}, y3 = {y}");

                    x *= zhuDongParamY;

                    _hAxis = (Mathf.Abs(x) <= GameSetting.ignoreX) ? 0 : x;
                    _vAxis = (Mathf.Abs(y) <= GameSetting.ignoreY) ? 0 : y;

                    Debug.Log($"左右翻转 hAxis = {_hAxis} vAxis = {_vAxis}");
                }
                catch (System.Exception e)
                {
                    Debug.LogWarning(e);
                }
            }
        }

        private void WriteCalibration(double[] value)
        {
            if (gameConfig.posture == Posture.Stand)
            {
                standA = value[0];
                standB = value[1];
                standC = value[2];
                standD = value[3];
            }
            else
            {
                seatA = value[0];
                seatB = value[1];
                seatC = value[2];
                seatD = value[3];
            }

            string path = gameConfig.posture == Posture.Stand ? standPath : seatPath;
            string[] lines = new string[4];
            for (int i = 0; i < lines.Length; i++)
            {
                if (gameConfig.posture == Posture.Stand)
                    lines[i] = $"stand{caliStr[i]}={value[i]}";
                else
                    lines[i] = $"seat{caliStr[i]}={value[i]}";
            }

            if (File.Exists(path))
            {
                File.WriteAllLines(path, lines);
                string name = gameConfig.posture == Posture.Stand ? "站姿" : "坐姿";
                Debug.Log($"写入{name}校准值");
            }
            else
            {
                Debug.Log($"{path} 不存在");
            }
        }

        private IEnumerator Fall()
        {
            while (fallThreshold > 0)
            {
                if ((tmpx + tmpy) < fallThreshold)
                {
                    // 摔倒
                    int result = -1;
                    //UIManager.Instance.ErrorBox($"检测到您已摔倒，是否继续游戏？", 1, i => result = i, "取消", "确定");
                    yield return new WaitUntil(() => result >= 0);
                    if (result == 0)
                    {
                        Application.Quit();
                        yield break;
                    }
                    //UIManager.Instance.ClearErrorBox();
                }

                yield return new WaitForSecondsRealtime(0.1f);
            }
        }

    }
}
